using System;
using System.Drawing;

namespace OhioState.Graphics.Proxy
{
    /// <summary>
    /// TexImage class used to read in textures for billboarding purposes
    /// </summary>
    [Serializable]
    public class TexImage : Texture2D
    {
        private String fileName;
        /// <summary>
        /// Constructor for TexImage
        /// </summary>
        /// <param name="name">name of the texture</param>
        /// <param name="filename">filename</param>
        public TexImage(String name, String filename)
            : base(name, 1, 1)
        {
            this.fileName = filename;
            using (Bitmap image = new Bitmap(fileName))
            {
                this.Width = image.Width;
                this.Height = image.Height;
            }
            TexelFormat texelFormat = new TexelFormat();
            texelFormat.Format = ImageFormat.RGBA;
            texelFormat.Type = ByteFormat.BYTE;
            this.TexelType = texelFormat;
        }
        /// <summary>
        /// Get the texel data as a multidimensional array [height,width,4]
        /// </summary>
        /// <param name="texels">A multidimensional array of size [height,width,4] is allocated and returned.</param>
        public override void GetTexture(out byte[,,] texels)
        {
            using (Bitmap image = new Bitmap(fileName))
            {
                texels = new byte[this.Height, this.Width, 4];
                for (int j = 0; j < this.Height; j++)
                {
                    for (int i = 0; i < this.Width; i++)
                    {
                        Color texel = image.GetPixel(i, j);
                        texels[j, i, 0] = texel.R;
                        texels[j, i, 1] = texel.G;
                        texels[j, i, 2] = texel.B;
                        texels[j, i, 3] = texel.A;
                    }
                }
            }
        }
        /// <summary>
        /// Get the texel data as a multidimensional array [height,width,4]
        /// </summary>
        /// <param name="texels">A multidimensional array of size [height,width,4] is allocated and returned.</param>
        public override void GetTexture(out byte[] texels)
        {

            //hack! not the best programming practice, better to write a separate method?
            //have to do this to avoid using the slow Bitmap; working directly with byte array
            //is much faster
            if (_imageByte != null)
            {
                texels = _imageByte;
                return;
            }

            int l = 0;
            using (Bitmap image = new Bitmap(fileName))
            {
                //have to flip the image - for some reason Bitmap reads it upside down
                image.RotateFlip(RotateFlipType.RotateNoneFlipY);

                _imageByte = new byte[this.Height * this.Width * 4];
                for (int j = 0; j < this.Height; j++)
                {
                    for (int i = 0; i < this.Width; i++)
                    {
                        Color texel = image.GetPixel(i, j);
                        _imageByte[l++] = texel.R;
                        _imageByte[l++] = texel.G;
                        _imageByte[l++] = texel.B;
                        _imageByte[l++] = texel.A;
                    }
                }
            }
            texels = _imageByte;
        }

        private ushort[] _imageShort;
        /// <summary>
        /// Get/Set Accessors for the image data in ushort
        /// </summary>
        public ushort[] ImageShort
        {
            set { _imageShort = value; }
            get { return _imageShort; }
        }


        private byte[] _imageByte;
        /// <summary>
        /// Get/set Accessors for image data in byte format
        /// </summary>
        public byte[] ImageByte
        {
            set 
            {
                // TODO why copy over?
                _imageByte = new byte[value.Length];
                for (int i = 0; i < value.Length; i++)
                {
                    _imageByte[i] = value[i];
                }
            }
            get { return _imageByte; }
        }
        /// <summary>
        /// Contructor for TexImage
        /// </summary>
        /// <param name="name">name of the texture</param>
        /// <param name="data">texture data</param>
        /// <param name="w">width</param>
        /// <param name="h">height</param>
        public TexImage(String name, ushort[] data, int w, int h)
            : base(name, 1, 1)
        {
            _imageShort = data;
            //_imageShort = new ushort[data.Length];
            //for (int i = 0; i < data.Length; i++)
            //{
            //    _imageShort[i] = data[i];
            //}
            this.Width = w;
            this.Height = h;
            TexelFormat texelFormat = new TexelFormat();
            texelFormat.Format = ImageFormat.RGBA16;
            texelFormat.Type = ByteFormat.UNSIGNED_SHORT;
            this.TexelType = texelFormat;
        }
        /// <summary>
        /// Constructor for TexImage
        /// </summary>
        /// <param name="name">name of the texture</param>
        /// <param name="data">texture data</param>
        /// <param name="w">width</param>
        /// <param name="h">height</param>
        public TexImage(String name, byte[] data, int w, int h)
            : base(name, 1, 1)
        {
            _imageByte = data;
            //_imageByte = new byte[data.Length];
            //for (int i = 0; i < data.Length; i++)
            //{
            //    _imageByte[i] = data[i];
            //}
            this.Width = w;
            this.Height = h;
            TexelFormat texelFormat = new TexelFormat();
            texelFormat.Format = ImageFormat.RGBA;
            texelFormat.Type = ByteFormat.BYTE;
            this.TexelType = texelFormat;
        }

        /// <summary>
        /// Implementation of Texture2D GetTextureShort method
        /// </summary>
        /// <param name="xDim"></param>
        /// <param name="yDim"></param>
        /// <returns></returns>
        public override ushort[] GetTextureShort(out int xDim, out int yDim)
        {
            //return _imageShort;//can I do this? or should create a copy?
            xDim = this.Width;
            yDim = this.Height;
            ushort[] result = new ushort[xDim * yDim * 4];
            for (int i = 0; i < _imageShort.Length; i++)
            {
                result[i] = _imageShort[i];
            }
            return result;
        }

        public TexImage(String name):base(name, 1, 1)
        {
        }

        //public override TextureProxy Clone()
        //{
        //    TexImage texImage;
        //    texImage = new TexImage(fileName,xDim, yDim,extension);
        //    return texImage;
        //}

    }

}
